﻿#include "position_container.h"
#include <data_types.hpp>

position_container::position_container()
{
}

position_container::~position_container()
{
}

void position_container::increase_position(const code_t& code, direction_type direction, double_t price, uint32_t volume)
{
	spin_lock lock(_mutex);
	auto& pos = _position_info[code];
	pos.id = code ;
	if(direction == DT_LONG)
	{
		pos.long_position.price = (pos.long_position.volume * pos.long_position.price + price * volume)/(pos.long_position.volume + volume);
		pos.long_position.volume += volume;
	}else if(direction == DT_SHORT)
	{
		pos.short_position.price = (pos.short_position.volume * pos.short_position.price + price * volume) / (pos.short_position.volume + volume);
		pos.short_position.volume += volume;
	}
}

void position_container::reduce_position(const code_t& code, direction_type direction, uint32_t volume, bool is_reduce_frozen )
{
	spin_lock lock(_mutex);
	auto it = _position_info.find(code);
	if(it == _position_info.end())
	{
		return;
	}
	if (direction == DT_LONG)
	{
		it->second.long_position.volume -= std::min<uint32_t>(volume, it->second.long_position.volume);
		if (is_reduce_frozen)
		{
			it->second.long_position.frozen -= std::min<uint32_t>(volume, it->second.long_position.frozen);
		}
	}
	else if (direction == DT_SHORT)
	{
		it->second.short_position.volume -= std::min<uint32_t>(volume, it->second.short_position.volume);
		if (is_reduce_frozen)
		{
			it->second.short_position.frozen -= std::min<uint32_t>(volume, it->second.short_position.frozen);
		}
	}
	if(it->second.empty())
	{
		_position_info.erase(it);
	}
}

void position_container::frozen_position(const code_t& code, direction_type direction, uint32_t volume)
{
	spin_lock lock(_mutex);
	auto it = _position_info.find(code);
	if (it == _position_info.end())
	{
		return ;
	}
	if (direction == DT_LONG)
	{
		it->second.long_position.frozen += std::min<uint32_t>(volume, it->second.long_position.volume);
	}
	else if (direction == DT_SHORT)
	{
		it->second.short_position.frozen += std::min<uint32_t>(volume, it->second.short_position.volume);
	}
}

void position_container::thawing_position(const code_t& code, direction_type direction, uint32_t volume)
{
	spin_lock lock(_mutex);
	auto it = _position_info.find(code);
	if (it == _position_info.end())
	{
		return ;
	}
	if (direction == DT_LONG)
	{
		it->second.long_position.frozen -= std::min<uint32_t>(volume, it->second.long_position.frozen);
	}
	else if (direction == DT_SHORT)
	{
		it->second.short_position.frozen -= std::min<uint32_t>(volume, it->second.short_position.frozen);
	}
}

position_info position_container::get_position_info(const code_t& code)const
{
	spin_lock lock(_mutex);
	auto it = _position_info.find(code);
	if (it != _position_info.end())
	{
		return it->second;
	}
	return position_info(code);
}

void position_container::get_all_position(std::vector<position_info>& position)const
{
	spin_lock lock(_mutex);
	for(auto&it : _position_info)
	{
		position.emplace_back(it.second);
	}
}

void position_container::clear()
{
	spin_lock lock(_mutex);
	_position_info.clear();
}